local Linq = {}

function Linq:Linq(data)
	if not data then
		return nil
	end
	local cdata = clone(data)
	local mettable = getmetatable(cdata)
	if mettable then
		if not mettable.__is_linq then
			local clinq = clone(Linq)
			setmetatable(clinq, {__index = mettable.__index})
			setmetatable(cdata, {__index = clinq, __is_linq = true})
		end
	else
	 	setmetatable(cdata, {__index = Linq, __is_linq = true})
	end
 	return cdata
end 

function Linq:Select(func)
	local data = {}

	for i,v in ipairs(self) do
		local d = func(v)
		if d then
			table.insert(data, d)
		end
	end

	return self:Linq(data)
end

function Linq:Where(func)
	local data = {}

	for i,v in ipairs(self) do
		if func(v) then
			table.insert(data, v)
		end
	end

	return self:Linq(data)
end

function Linq:Sum(func)
	local sum = 0

	if func then
		for _, item in ipairs(self) do
			sum = sum + func(item)
		end
	else
		for _, item in ipairs(self) do
			sum = sum + item
		end
	end

	return sum
end

function Linq:All(func)
	local all = true

	for _, item in ipairs(self) do
		if not func(item) then
			all = false
			break
		end
	end

	return all
end

function Linq:Any(func)
	local any = false

	for _, item in ipairs(self) do
		if func(item) then
			any = true
			break
		end
	end

	return any
end

function Linq:First(func)
	local data = nil

	for i,v in ipairs(self) do
		if not func or func(v) then
			data = v
			break
		end
	end

	return data and self:Linq(data)
end

function Linq:Get(name)
	return self[name] and self:Linq(self[name])
end

function Linq:Sort(func)
	local cdata = clone(self)

	table.sort(cdata, func)

	return self:Linq(cdata)
end

function Linq:Clear()
	setmetatable(self, nil)
	return self
end

-- cc.exports.Linq = Linq

return Linq